/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core;

import javax.microedition.midlet.MIDlet;
import com.sun.lwuit.Display;
import com.sun.lwuit.Label;
import com.sun.lwuit.TextField;
import com.sun.lwuit.plaf.UIManager;
import com.sun.lwuit.util.Resources;
import datamodel.Order;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import network.Connection;
import network.PacketBuilder;
import network.packets.ChangeDriverStateFromServer;
import network.packets.DistrictChangedResponce;
import network.packets.DriverInBlackList;
import network.packets.LoginResponcePacket;
import network.packets.OrderCancel;
import network.packets.OrderDoneResponce;
import network.packets.OrderYourResponce;
import network.packets.Packet;
import network.packets.ServerMessage;
import network.packets.SetOrderResponce;
import network.packets.StartOrderResponce;
import network.packets.TimerCorrectorResponce;
import view.TextForm;
import view.LoginEnterForm;
import view.MainForm;
import view.MessageBox;
import view.ProgressForm;
import view.SetOrderForm;
import view.UpdateForm;
import view.additional.FunctionsMaskListener;



//Сделал
//5)и так ещё добавь в диспетчерской - "вызвать клиента"... и пока сделай невидимой "связь с клиентом" 

//Bug
//-------------------------

//Обрабатывать логин с одним и тем же логин-паролем двух водил!
//Настройки под пароль

//Стать на стоянку с несуществующим ИД(прибавить при отправке большое число)
//Что должно происходить если приходит второе соединение с позывным паролем, который сейчас залогинен?

//Узнать, может ли приходить 11 пакет для текущего заказа. Если да - перенести из драйверменеджера в менеджер заказов текущий заказ и при 11 пакете учесть текущий заказ 
//Возможно отказаться от диалогов для messageBox?
//Тест на тачскрине
//Проверить что все методы в менеджере заказов синхронные
//Удалить тестовый логин-пароль
//Удалить вывод в консоль в классе соединения
//Удалить print в пакетах
//Все //ToDo Kvest

/**
 *
 * @author Kvest
 */
public class TaxiMIDlet extends MIDlet
{    
    private static TaxiMIDlet midlet;
    
    private boolean pause = false;
    
    private MainForm mainForm;
    private TextForm messageForm;
    private SetOrderForm setOrderForm;
    
    private String clientVersion;
    
    private static final long RECONNECT_TIME_PERIOD = 15000L;
    private Timer reconnectTimer;
    
    private FunctionsMaskListener functionsMaskListener = null;
    
    public TaxiMIDlet()
    {
        pause = false;
        
        //Инициализируем визуальную библиотеку
        Display.init(this);
        Display.getInstance().setThirdSoftButton(!Display.getInstance().isTouchScreenDevice());
        
        clientVersion = "";
        
        //Устанавливаем некоторые обработчики
        Connection.getConnection().setConnectionNotifier(new Connection.ConnectionNotifier() 
        {
            public void connectionEstablished() 
            {
                byte[] data = PacketBuilder.createLoginPacket(Settings.getSettings().getLogin(),
                                                              Settings.getSettings().getPassword(), clientVersion);
                //Останавливаем таймер переподсоединения
                stopReconnectTimer();
                
                if (!Connection.getConnection().send(data))
                {
                    //Отсанавливаем соединение
                    Connection.getConnection().stop();
                    
                    //Выталкиваем окна до самого первого(гл.меню)
                    while (ScreenEngine.getEngine().getScreensCount() > 1)
                    {
                        ScreenEngine.getEngine().pop(false);
                    }
                    //Отображаем главное меню
                    ScreenEngine.getEngine().showCurrent();
                    
                    //Отображаем сообщение с ошибкой
                   MessageBox.showModeless("error", "login_err"); 
                }
            }
        });
        Connection.getConnection().setConnectionErrorListener(new Connection.ConnectionErrorListener() 
        {
            public void connectionError(int code) 
            {
                //Выталкиваем окна до самого первого(гл.меню)
                while (ScreenEngine.getEngine().getScreensCount() > 1)
                {
                    ScreenEngine.getEngine().pop(false);
                }
                //Отображаем главное меню
                ScreenEngine.getEngine().showCurrent();

                //Отображаем сообщение с ошибкой
                MessageBox.showModeless("error", "net_err_" + Integer.toString(code));  
  
                //Играем музыку
                MediaManager.getManager().playMusic(Settings.getSettings().getConnectionErrorMelodyId());
            }
        });
        
        registerPacketListeners();
    }
    
    private void registerPacketListeners()
    {
        Connection connetcion = Connection.getConnection();
        connetcion.setPacketListener(Packet.DRIVER_IN_BLACK_LIST_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet) 
            {
                //Помечаем как в черном списке
                DriverManager.getManager().setInBlackList(((DriverInBlackList)packet).isInBlacklist());
                
                //Перерисовываем текущую форму
                ScreenEngine.getEngine().showCurrent();
            }
        });
        
        connetcion.setPacketListener(Packet.LOGIN_RESPONCE, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                LoginResponcePacket responce = (LoginResponcePacket)packet;
                if (responce.getResult() == LoginResponcePacket.RESULT_OK)
                {
                    //Сохраняем полученные данные
                    DriverManager driverManager = DriverManager.getManager();
                    driverManager.setDriverID(responce.getDriverID());
                    driverManager.setCurrenntState(responce.getDriverState());
                    driverManager.setNextState(responce.getDriverNextState());
                    driverManager.setDistrictID(responce.getDistrictID());
                    driverManager.setCurrentOrderID(responce.getCurrentOrderID());
                    driverManager.setCurrentOrderText(responce.getCurrentOrderText());
                    
                    //Устанавливаем список позывных
                    mainForm.setDriversOrder(responce.getDriversOrder());
                    
                    //Настраиваем "Функции"
                    maskChangedEvent(responce.getFunctionsMask());
                    
                    //Удаляем форму загрузки
                    if (ScreenEngine.getEngine().getCurrent() instanceof ProgressForm)
                    {
                        ScreenEngine.getEngine().popProgressForm(true);
                    }
                    else
                    {
                        ScreenEngine.getEngine().showCurrent();
                    }
                    
                    //Переставитьт слушателя ошибки соединения
                    resetConnectionErrorListener();  
                    
                    //Смотрим есть ли новая версия
                    checkNeedUpdate(responce.getActualClientVersion(), responce.getActualClientLink(), responce.isMustUpdate());
                    
                    //Запрашиваем архив сообщений
                    byte[] data = PacketBuilder.createMessagesArchiveRequest(driverManager.getDriverID());
                    Connection.getConnection().send(data);
                }
                else
                {
                    //Останавливаем соединение
                    Connection.getConnection().stop();
                    
                    //Удаляем форму загрузки
                    if (ScreenEngine.getEngine().getCurrent() instanceof ProgressForm)
                    {
                        ScreenEngine.getEngine().popProgressForm(true);
                    }
                    else
                    {
                        ScreenEngine.getEngine().showCurrent();
                    }
                    
                    //Показываем сообщение с ошибкой
                   MessageBox.showModeless("error", responce.getResult() == LoginResponcePacket.RESULT_WRONG_AUTH_DATA ? "wrong_auth" : "login_error");
                }
            }
        });
        connetcion.setPacketListener(Packet.ORDER_YOUR_RESPONCE,  new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet) 
            {
                OrderYourResponce responce = (OrderYourResponce)packet;
                
                //Переходим на главную форму
                //Выталкиваем окна до самого первого(гл.меню)
                ScreenEngine.getEngine().popTo(0);
                
                //Показываем сообщение
                MessageBox.showModeless("message", (new Label("order_your")).getText() + "\n" + responce.getFullText());
            }
        });
        
        connetcion.setPacketListener(Packet.SET_ORDER_RESPONCE,  new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet) 
            {
                SetOrderResponce responce = (SetOrderResponce)packet;
                
                //Проигрываем музыку
                MediaManager.getManager().playMusic(Settings.getSettings().getStartOrderMelodyId());
        
                //Отображаем форму с заказом
                showSetOrderForm(responce.getOrder());
            }
        });
        
        connetcion.setPacketListener(Packet.START_ORDER_RESPONCE,  new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                StartOrderResponce responce = (StartOrderResponce)packet;
                
                //Устанавливаем текущий заказ
                DriverManager.getManager().setCurrentOrderID(responce.getOrderID());
                DriverManager.getManager().setCurrentOrderText(responce.getFullText());
                
                //Обновляем форму
                if (ScreenEngine.getEngine().getCurrent() instanceof MainForm)
                {
                    ((MainForm)ScreenEngine.getEngine().getCurrent()).update(true);
                }
                else
                {
                    //Переходим на главную форму
                    ScreenEngine.getEngine().popTo(0);
                }
                
                //Показываем сообщение
                MessageBox.showModeless("message", (new Label("start_order")).getText() + "\n" + responce.getFullText());
                
                //Играем музыку
                MediaManager.getManager().playMusic(Settings.getSettings().getStartOrderMelodyId());
            }
        });
        
        connetcion.setPacketListener(Packet.CHANGE_DRIVER_STATE_FROM_SERVER, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet) 
            {
                ChangeDriverStateFromServer responce = (ChangeDriverStateFromServer)packet;
                
                //Меняем статусы водителя
                DriverManager.getManager().setCurrenntState(responce.getState());
                DriverManager.getManager().setNextState(responce.getNextState());
                
                 //Настраиваем "Функции"
                maskChangedEvent(responce.getFunctionsMask());
                
                //Отображаем сообщение
               // MessageBox.showModeless("message", (new Label("new_state")).getText() + responce.getState().getName());
            }
        });

        connetcion.setPacketListener(Packet.ORDER_CANCEL_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                OrderCancel responce = (OrderCancel)packet;

                if (responce.getOrderID() == DriverManager.getManager().getCurrentOrderID())
                {
                    //Сбрасываем текущий заказ
                    DriverManager.getManager().setCurrentOrderID(DriverManager.UNKNOWN_VALUE);
                    DriverManager.getManager().setCurrentOrderText("");

                    //Обновляем форму
                    if (ScreenEngine.getEngine().getCurrent() instanceof MainForm)
                    {
                        ((MainForm)ScreenEngine.getEngine().getCurrent()).update(true);
                    }

                    //Отображаем сообщение
                    MessageBox.showModeless("", responce.getMessage());
                    
                    //Играем музыку
                    MediaManager.getManager().playMusic(Settings.getSettings().getCancelOrderMelodyId());
                }
            }
        });

        connetcion.setPacketListener(Packet.ORDER_DONE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                OrderDoneResponce responce = (OrderDoneResponce)packet;

                //Сбрасываем текущий заказ
                DriverManager.getManager().setCurrentOrderID(DriverManager.UNKNOWN_VALUE);
                DriverManager.getManager().setCurrentOrderText("");

                //Обновляем форму
                if (ScreenEngine.getEngine().getCurrent() instanceof MainForm)
                {
                    ((MainForm)ScreenEngine.getEngine().getCurrent()).update(true);
                }
            }
        });
        
        connetcion.setPacketListener(Packet.DISTRICT_CHANGED, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                DistrictChangedResponce responce = (DistrictChangedResponce)packet;

                //Обновляем текущее местоположение
                DriverManager.getManager().setDistrictID(responce.getDistrictID());

                //Обновляем форму
                if (ScreenEngine.getEngine().getCurrent() instanceof MainForm)
                {
                    ((MainForm)ScreenEngine.getEngine().getCurrent()).update(true);
                }
            }
        });

        connetcion.setPacketListener(Packet.SERVER_MESSAGE_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                ServerMessage responce = (ServerMessage)packet;

                //Просто отображаем сообщением
                if (messageForm == null)
                {
                    messageForm = new TextForm();
                }
                messageForm.setText(responce.getMessage());
                ScreenEngine.getEngine().push(messageForm);
            }
        });

        connetcion.setPacketListener(Packet.PING_REQUEST, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                //Отправляем ответ
                byte[] data = PacketBuilder.createPingResponce();
                Connection.getConnection().send(data);
            }
        });
        
        connetcion.setPacketListener(Packet.TIMER_CORRECTOR_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                TimerCorrectorResponce responce = (TimerCorrectorResponce)packet;
                
                //Корректируем время таймера
                DriverManager.getManager().correctTimerTime(responce.getCorrection());
            }
        });
        
        //Создаем менеджер заказов и сообщений - чтоб подписаться на события
        OrderManager.getManager();
        MessageManager.getManager();
    }
    
    public void startApp()
    {
        if (pause)
        {
            return;
        }
        
        midlet = this;

        clientVersion = getAppProperty("MIDlet-Version");
        if (clientVersion == null)
        {
            clientVersion = "";
        }
           
        Settings settings = Settings.getSettings();
        
        //Устанавливаем тему отображения компонентов
        try
        {
            Resources r = Resources.open("/TaxiTheme.res");
            Hashtable theme = r.getTheme(r.getThemeResourceNames()[0]);
            
            //Шрифт(изменяем только если средний или большой)
            switch(settings.getFontSize())
            {
                case Settings.FS_MIDDLE : theme.put("font", r.getFont("MiddleFont")); break;
                case Settings.FS_BIG : theme.put("font", r.getFont("BigFont")); break;
            }
            
            UIManager.getInstance().setThemeProps(theme);
            Hashtable localize = r.getL10N("taxi", "ru");
            UIManager.getInstance().setResourceBundle(localize);
        }catch (Exception e) {}
        
        //Регистрируем новую клавиатуру
        registerRussionKeyboard();
        
        //Добавляем главную форму
        mainForm = new MainForm();
        ScreenEngine.getEngine().push(mainForm);
     
        //Делаем чтоб не потухал экран на Nokia
        startBacklightTimer();
        
        //ToDo Kvest 
        //delete
        if ("wtk-emulator".equals(System.getProperty("device.model")))
        {
            settings.setLogin("999");
            settings.setPassword("91891");
            settings.setHost("192.168.1.121:3426");
        }
        //settings.setHost("79.134.18.222:3427");
         
        //Если нет логина или пароля - запрашиваем, иначе пытаемся установить соединение с сервером
        if (settings.getLogin().equals("") || settings.getPassword().equals(""))
        {
            ScreenEngine.getEngine().push(new LoginEnterForm());
        }
        else
        {
            //Отображаем форму прогресса
            ScreenEngine.getEngine().push(new ProgressForm());
            
            //Начинаем соединение
            Connection.getConnection().start(Settings.getSettings().getHost(), Settings.getSettings().getSecondHost());
        }
    }

    public void pauseApp() 
    {
        pause = true;
    }

    public void destroyApp(boolean unconditional)
    {
        notifyDestroyed();
    }
    
    private void startBacklightTimer()
    {
        try
        {
            Class.forName("com.nokia.mid.ui.DeviceControl");
            Timer timer = new Timer();
            timer.schedule(new TimerTask()
                            {
                                public void run()
                                {
                                    try
                                    {
                                        com.nokia.mid.ui.DeviceControl.setLights(0, 100); 
                                    }catch(Exception ex){}
                                }
                            }, 10000, 10000);
            
        }
        catch(Exception e){}
    }
    
    public static TaxiMIDlet getMidlet()
    {
        return midlet;
    }
    
    private void stopReconnectTimer()
    {
        if (reconnectTimer != null)
        {
            reconnectTimer.cancel();
        }
        reconnectTimer = null;
    }
    
    private void startReconnectTimer()
    {
        //Ели был запущен - останавливаем
        stopReconnectTimer();
        
        reconnectTimer = new Timer();
        reconnectTimer.schedule(new TimerTask()
        {
            public void run()
            {                 
                //Начинаем соединение
                Connection.getConnection().start(Settings.getSettings().getHost(), Settings.getSettings().getSecondHost());
            }
        }, RECONNECT_TIME_PERIOD);
    }
    
    private void resetConnectionErrorListener()
    {
        Connection.getConnection().setConnectionErrorListener(new Connection.ConnectionErrorListener() 
        {
            public void connectionError(int code) 
            {       
                //Выталкиваем на главную форму
                ScreenEngine.getEngine().popTo(0);
                        
                //Запускаем таймер переподсоединения
                startReconnectTimer();
                
                //Играем музыку
                MediaManager.getManager().playMusic(Settings.getSettings().getConnectionErrorMelodyId());
            }
        });
    }
    
    private void checkNeedUpdate(String actualClientVersion, String actualClientLink, boolean mustUpdate)
    {
        double clientVersionNumber = 0, actualClientVersionNumber = 0;
        try
        {
            clientVersionNumber = Double.parseDouble(clientVersion); 
            actualClientVersionNumber = Double.parseDouble(actualClientVersion);
        }
        catch(Exception ex){}
        
        if (actualClientVersionNumber > clientVersionNumber)
        {
            if (mustUpdate)
            {
                //Останавливаем соединение
                Connection.getConnection().stop();
            }
            
            //Отображаем форму обновления
            ScreenEngine.getEngine().push(new UpdateForm(actualClientLink,mustUpdate));
        }
    }

    private void maskChangedEvent(int mask)
    {
        Settings.getSettings().setFunctionsMask(mask);
        if (functionsMaskListener != null)
        {
            functionsMaskListener.maskChanged(mask);
        }
    }
    
    public void setFunctionsMaskListener(FunctionsMaskListener functionsMaskListener) 
    {
        this.functionsMaskListener = functionsMaskListener;
    }
    
    private void showSetOrderForm(Order order)
    {
        if (setOrderForm == null)
        {
            setOrderForm = new SetOrderForm();
        }

        //Устанавливаем заказ
        setOrderForm.setShownOrder(order);
        
        //Отображаем
        ScreenEngine.getEngine().push(setOrderForm);
    }
    
    public static void registerRussionKeyboard()
    {
        final String[] LOWER_CASE_KEY_CODES = {
            // 0
            " +0",
            // 1
            ".,?!'\"1-()@/:_",
            // 2
            //"\u05d3\u05d4\u05d52",
            "абвг",
            // 3
            //"\u05d0\u05d1\u05d23",
            "дежз",
            // 4
            //"\u05de\u05dd\u05e0\u05df4",
            "ийкл",
            // 5
            //"\u05d9\u05db\u05da\u05dc5",
            "мноп",
            // 6
            //"\u05d6\u05d7\u05d86",
            "рсту",
            // 7
            //"\u05e8\u05e9\u05ea7",
            "фхцч",
            // 8
            //"\u05e6\u05e5\u05e78",
            "шщъы",
            // 9
            //"\u05e1\u05e2\u05e4\u05e39"
            "ьэюя"
        };

        Hashtable values = new Hashtable();
        for(int iter = 0 ; iter < LOWER_CASE_KEY_CODES.length ; iter++)
        {
            values.put(new Integer('0' + iter), LOWER_CASE_KEY_CODES[iter]);
        }
        TextField.addInputMode("абв", values, false);
        
        final String[] UPPER_CASE_KEY_CODES = {
            // 0
            " +0",
            // 1
            ".,?!'\"1-()@/:_",
            // 2
            //"\u05d3\u05d4\u05d52",
            "АБВГ",
            // 3
            //"\u05d0\u05d1\u05d23",
            "ДЕЖЗ",
            // 4
            //"\u05de\u05dd\u05e0\u05df4",
            "ИЙКЛ",
            // 5
            //"\u05d9\u05db\u05da\u05dc5",
            "МНОП",
            // 6
            //"\u05d6\u05d7\u05d86",
            "РСТУ",
            // 7
            //"\u05e8\u05e9\u05ea7",
            "ФХЦЧ",
            // 8
            //"\u05e6\u05e5\u05e78",
            "ШЩЪЫ",
            // 9
            //"\u05e1\u05e2\u05e4\u05e39"
            "ЬЭЮЯ"
        };
        
        values = new Hashtable();
        for(int iter = 0 ; iter < UPPER_CASE_KEY_CODES.length ; iter++)
        {
            values.put(new Integer('0' + iter), UPPER_CASE_KEY_CODES[iter]);
        }
        TextField.addInputMode("АБВ", values, false);
    }
}
